/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-01-27     98409       the first version
 */
#include "temp.h"

/** @addtogroup ADC_ADC1_TEMP
 * @{
 */

ADC_InitType ADC_InitStructure;
ADC_InitTypeEx ADC_InitStructureEx;
DMA_InitType DMA_InitStructure;
__IO uint16_t ADCConvertedValue;



#define Vc0        0    //X
#define Tc1        1.5f
/*V30 is the voltage value at 30 degree Celsius by factory default*/
uint16_t  V30 = 0;
uint16_t  ADvalue = 0;
uint32_t  temp = 0;

#ifdef  DEFINEFLOAT   //Float
__IO float TempValue;
/*xx mv per degree Celsius  by datasheet define*/
#define AVG_SLOPE  0.0041f
/**
 * @brief  Cal temp use float result.
 */
float TempCal(void)
{
    float Temperate;
    /* Get the temperature inside the chip */
    Temperate=((V30+Vc0-ADCConvertedValue)*3.3/4095)/AVG_SLOPE+30.0f-Tc1;
    return Temperate;
}
#else
__IO int16_t TempValue;
/*xx mv per degree Celsius  by datasheet define*/
#define AVG_SLOPE  41
/**
 * @brief  Cal temp use integer result.
 */
 
int16_t TempCal(void)
{
    int16_t Temperate;
    /* Get the temperature inside the chip */
    Temperate=(int16_t)((((V30+Vc0-ADCConvertedValue)*33*10000)/(4095*10))/AVG_SLOPE+30-Tc1);
    return Temperate;
}
#endif

void tempInit(void)
{
    /* Enable peripheral clocks ------------------------------------------------*/
    /* Enable DMA1 and DMA2 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);

    /* Enable ADC1 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1,ENABLE);

    /* RCC_ADCHCLK_DIV16*/
    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);

    /* DMA1 channel1 configuration ----------------------------------------------*/
    DMA_DeInit(DMA1_CH1);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&ADC1->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)&ADCConvertedValue;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = 1;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_DISABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(DMA1_CH1, &DMA_InitStructure);
    /* Enable DMA1 channel1 */
    DMA_EnableChannel(DMA1_CH1, ENABLE);

    /* ADC1 configuration ------------------------------------------------------*/
    ADC_InitStructure.WorkMode       = ADC_WORKMODE_INDEPENDENT;
    ADC_InitStructure.MultiChEn      = ENABLE;
    ADC_InitStructure.ContinueConvEn = ENABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = 1;
    ADC_Init(ADC1, &ADC_InitStructure);
    /* ADC1 temp sensor enable */
    ADC_EnableTempSensorVrefint(ENABLE);

    ADC_InitStructureEx.VbatMinitEn = ENABLE;
    ADC_InitStructureEx.DeepPowerModEn = DISABLE;
    ADC_InitStructureEx.JendcIntEn = DISABLE;
    ADC_InitStructureEx.EndcIntEn = DISABLE;
    ADC_InitStructureEx.ClkMode = ADC_CTRL3_CKMOD_AHB;
    ADC_InitStructureEx.CalAtuoLoadEn = DISABLE;
    ADC_InitStructureEx.DifModCal = false;
    ADC_InitStructureEx.ResBit = ADC_CTRL3_RES_12BIT;
    ADC_InitStructureEx.SampSecondStyle = false;
    ADC_InitEx(ADC1, &ADC_InitStructureEx);
    /* ADC1 regular configuration */
    ADC_ConfigRegularChannel(ADC1, ADC_CH_16, 1, ADC_SAMP_TIME_239CYCLES5);//ADC_CH_16：测温度，ADC_CH_18：测内部1.2V基准
    /* ADC1 temp sensor enable */
    ADC_EnableTempSensorVrefint(ENABLE);
    /* Enable ADC1 DMA */
    ADC_EnableDMA(ADC1, ENABLE);

    /* Enable ADC1 */
    ADC_Enable(ADC1, ENABLE);
    /*Check ADC Ready*/
    while(ADC_GetFlagStatusNew(ADC1,ADC_FLAG_RDY) == RESET);
    /* Start ADC1 calibration */
    ADC_StartCalibration(ADC1);
    /* Check the end of ADC1 calibration */
    while (ADC_GetCalibrationStatus(ADC1));

    /* Start ADC1 Software Conversion */
    ADC_EnableSoftwareStartConv(ADC1, ENABLE);

    V30 = *(__IO uint32_t*)((uint32_t)0x1FFFF7D0);
}
